package com.syh.jn.scm.service.impl.supplier.finance;

import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.domain.DomainEvent;
import com.syh.core.ddd.event.DomainEventBus;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.jn.scm.domain.downstream.entity.purchase.DownPurchaseOrder;
import com.syh.jn.scm.domain.downstream.event.DownPurchaseOrderEvent;
import com.syh.jn.scm.domain.supplier.entity.finance.OrderExpensesBill;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseOrder;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleOrder;
import com.syh.jn.scm.domain.supplier.event.PurchaseOrderEvent;
import com.syh.jn.scm.domain.supplier.event.SaleOrderEvent;
import com.syh.jn.scm.domain.supplier.event.finance.OrderExpensesBillEvent;
import com.syh.jn.scm.domain.supplier.repository.finance.OrderExpensesBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.finance.OrderExpensesBillRepository;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseOrderReadRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleOrderReadRepository;
import com.syh.jn.scm.domain.upstream.entity.sale.UpSaleOrder;
import com.syh.jn.scm.domain.upstream.event.UpSaleOrderEvent;
import com.syh.jn.scm.dto.supplier.finance.orderExpensesBill.OrderExpensesBillMto;
import com.syh.jn.scm.dto.supplier.finance.orderExpensesBill.OrderExpensesBillSto;
import com.syh.jn.scm.dto.supplier.finance.orderExpensesBill.OrderExpensesBillVo;
import com.syh.jn.scm.infrastructure.eventBus.reflex.ReflexEventBus;
import com.syh.jn.scm.service.api.supplier.finance.OrderExpensesBillService;
import com.syh.jn.scm.service.api.supplier.finance.enums.OrderExpensesBillEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service
@Transactional
public class OrderExpensesBillServiceImpl implements OrderExpensesBillService {

  @Autowired
  private OrderExpensesBillRepository orderExpensesBillRepository;
  @Resource(name = "orderExpensesBillReadRepositoryMbImpl")
  private OrderExpensesBillReadRepository orderExpensesBillReadRepository;

  /**
   * 费用表确认
   * @param id
   * @param confirmTimeStamp
   */
  @Override
  public void confirm(Long id, Long confirmTimeStamp) {
    OrderExpensesBill orderExpensesBill = this.orderExpensesBillRepository.getById(id);
    orderExpensesBill.confirm(confirmTimeStamp);
    this.orderExpensesBillRepository.update(orderExpensesBill,false);
    this.publicEvent(OrderExpensesBillEvent.buildOrderExpensesBillConfirmEvent(new Object[]{orderExpensesBill}));
  }

  /**
   * 费用表取消确认
   * @param id
   */
  @Override
  public void cancel(Long id) {
    OrderExpensesBill orderExpensesBill = this.orderExpensesBillRepository.getById(id);
    OrderExpensesBill oldBill = this.orderExpensesBillRepository.getById(id);
    orderExpensesBill.cancel();
    this.orderExpensesBillRepository.update(orderExpensesBill,false);
    this.publicEvent(OrderExpensesBillEvent.buildOrderExpensesBillCancelEvent(new Object[]{orderExpensesBill,oldBill}));
  }

  @Override
  public Long save(OrderExpensesBillSto sto) {
    OrderExpensesBill orderExpensesBill = new OrderExpensesBill(sto);
    Long id = this.orderExpensesBillRepository.add(orderExpensesBill);
    orderExpensesBill.setId(id);
    this.publicEvent(OrderExpensesBillEvent.buildOrderExpensesBillCreatedEvent(new Object[]{orderExpensesBill}));
    return id;
  }

  @Override
  public void delete(Long id) {
    OrderExpensesBill orderExpensesBill = this.orderExpensesBillRepository.getById(id);
    orderExpensesBill.destory();
    this.orderExpensesBillRepository.remove(orderExpensesBill);
    this.publicEvent(OrderExpensesBillEvent.buildOrderExpensesBillDeletedEvent(new Object[]{orderExpensesBill}));
  }

  @Override
  public OrderExpensesBillVo getById(Long id) {
    return this.orderExpensesBillReadRepository.getById(id);
  }

  @Override
  public boolean contains(Long id) {
    return this.orderExpensesBillReadRepository.contains(id);
  }

  @Override
  public List<OrderExpensesBillVo> findList(Wrapper wrapper) {
    return this.orderExpensesBillReadRepository.getList(wrapper);
  }

  @Override
  public List<OrderExpensesBillVo> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return this.orderExpensesBillReadRepository.findListPage(wrapper,startRow,count);
  }

  @Override
  public OrderExpensesBillVo getOne(Wrapper wrapper) {
    return this.orderExpensesBillReadRepository.getOne(wrapper);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return this.orderExpensesBillReadRepository.getCount(wrapper);
  }

  @Override
  public void update(OrderExpensesBillMto orderExpensesBillMto) {
    OrderExpensesBill orderExpensesBill = this.orderExpensesBillRepository.getById(orderExpensesBillMto.getId());
    orderExpensesBill.modify(orderExpensesBillMto);
    this.orderExpensesBillRepository.update(orderExpensesBill);
    this.publicEvent(OrderExpensesBillEvent.buildOrderExpensesBillUpdatedEvent(new Object[]{orderExpensesBill}));
  }

  /**
   * 消费者：监听销售单取消确认，关联的费用表取消确认
   * @param saleOrder
   */
  @DomainEventHandle(SaleOrderEvent.SALEORDER_CANCEL_CONFIRM)
  protected void handleSaleOrderCancelConfirm(SaleOrder saleOrder) {
    if (saleOrder.getOrderExpensesBillId() != null) {
      OrderExpensesBill orderExpensesBill = this.orderExpensesBillRepository.getById(saleOrder.getOrderExpensesBillId());
      if (OrderExpensesBillEnums.State.CONFIRM.getStatus().equals(orderExpensesBill.getState())) {
        this.cancel(orderExpensesBill.getId());
      }
    }
  }

  /**
   * 消费者：监听销售单取消，删除关联的费用表
   * @param saleOrder
   */
  @DomainEventHandle(SaleOrderEvent.SALEORDER_CANCEL)
  protected void handleSaleOrderCancel(SaleOrder saleOrder) {
    if (saleOrder.getOrderExpensesBillId() != null) {
      OrderExpensesBill orderExpensesBill = this.orderExpensesBillRepository.getById(saleOrder.getOrderExpensesBillId());
      this.delete(orderExpensesBill.getId());
    }
  }

  /**
   * 消费者：监听下游采购单取消，取消关联的费用表
   * @param downPurchaseOrder
   */
  @DomainEventHandle(DownPurchaseOrderEvent.DOWN_PURCHASE_ORDER_CANCEL)
  protected void handleDownPurchaseOrderCancel(DownPurchaseOrder downPurchaseOrder) {
    SaleOrderReadRepository saleOrderReadRepository = (SaleOrderReadRepository) SpringContextUtils.getBean("saleOrderRepositoryImpl");
    SaleOrder saleOrder = saleOrderReadRepository.getById(downPurchaseOrder.getId());
    this.handleSaleOrderCancel(saleOrder);
  }
  /**
   * 消费者：监听上游销售单删除，关联的费用表一并删除
   * @param upSaleOrder
   */
  @DomainEventHandle(UpSaleOrderEvent.UP_SALE_ORDER_CANCEL)
  protected void handleUpSaleOrderCancel(UpSaleOrder upSaleOrder) {
    PurchaseOrderReadRepository purchaseOrderReadRepository = (PurchaseOrderReadRepository) SpringContextUtils.getBean("purchaseOrderRepositoryImpl");
    PurchaseOrder purchaseOrder = purchaseOrderReadRepository.getById(upSaleOrder.getId());
    if (purchaseOrder.getOrderExpensesBillId() != null) {
      this.delete(purchaseOrder.getOrderExpensesBillId());
    }
  }

  /**
   * 消费者：监听上游销售单删除，关联的费用表一并删除
   * @param upSaleOrder
   */
  @DomainEventHandle(UpSaleOrderEvent.UP_SALE_ORDER_CANCEL_CONFIRM)
  protected void handleUpSaleOrderCancelConfirm(UpSaleOrder upSaleOrder) {
    PurchaseOrderReadRepository purchaseOrderReadRepository = (PurchaseOrderReadRepository) SpringContextUtils.getBean("purchaseOrderRepositoryImpl");
    PurchaseOrder purchaseOrder = purchaseOrderReadRepository.getById(upSaleOrder.getId());
    if (purchaseOrder.getOrderExpensesBillId() != null) {
      OrderExpensesBill orderExpensesBill = orderExpensesBillRepository.getById(purchaseOrder.getOrderExpensesBillId());
      this.cancel(orderExpensesBill.getId());
    }
  }
  /**
   * 消费者：监听采购单取消，关联的费用表一并删除
   * @param purchaseOrder
   */
  @DomainEventHandle(PurchaseOrderEvent.PURCHASE_ORDER_CANCEL)
  protected void handlePurchaseOrderCancel(PurchaseOrder purchaseOrder) {
    if (purchaseOrder.getOrderExpensesBillId() != null) {
      this.delete(purchaseOrder.getOrderExpensesBillId());
    }
  }

  /**
   * 发布事件
   *
   * @param event
   */
  //TODO 暂时先写在service内
  public void publicEvent(DomainEvent event) {
    DomainEventBus bus = ReflexEventBus.getEventBus();
    bus.publicEvent(event);
  }
}
